package com.atguigu.controller;


import com.atguigu.client.OrderFeignClient;
import com.atguigu.constant.MqConst;
import com.atguigu.constant.RedisConst;
import com.atguigu.entity.OrderInfo;
import com.atguigu.entity.PrepareSeckillOrder;
import com.atguigu.entity.SeckillProduct;
import com.atguigu.entity.UserSeckillSkuInfo;
import com.atguigu.result.RetVal;
import com.atguigu.result.RetValCodeEnum;
import com.atguigu.service.SeckillProductService;
import com.atguigu.util.AuthContextHolder;
import com.atguigu.util.DateUtil;
import com.atguigu.util.MD5;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 
 * @since 2022-09-18
 */
@RestController
@RequestMapping("/seckill")
public class SeckillController {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillProductService seckillProductService;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private OrderFeignClient orderFeignClient;

    //1.查询所有秒杀商品
    @GetMapping("queryAllSeckillProduct")
    public RetVal queryAllSeckillProduct(){
        List<SeckillProduct> seckillProductList = redisTemplate.boundHashOps(RedisConst.SECKILL_PRODUCT).values();
        return RetVal.ok(seckillProductList);
    }

    //2.根据skuId 获取秒杀对象数据
    @GetMapping("getSeckillProductBySkuId/{skuId}")
    public RetVal getSeckillProductBySkuId(@PathVariable Long skuId){
        SeckillProduct seckillProduct = seckillProductService.getSeckillProductFromRedis(skuId);
        return RetVal.ok(seckillProduct);
    }

    //3.生成抢购码  //api.gmall.com/seckill/generateSeckillCode/33
    @GetMapping("generateSeckillCode/{skuId}")
    public RetVal generateSeckillCode(@PathVariable Long skuId, HttpServletRequest request){
        //1.判断是否登录
        String userId = AuthContextHolder.getUserId(request);
        if (!StringUtils.isEmpty(userId)) {
            //2.从缓存中拿到秒杀商品的信息 获取开始时间 结束时间
            SeckillProduct seckillProduct = seckillProductService.getSeckillProductFromRedis(skuId);
            //判断当前时间是否为秒杀范围内
            Date nowTime = new Date();
            if (DateUtil.dateCompare(seckillProduct.getStartTime(),nowTime)&&DateUtil.dateCompare(nowTime,seckillProduct.getEndTime())){
                //3.生成抢购码
                String seckillCode = MD5.encrypt(userId);
                return RetVal.ok(seckillCode);
            }
        }
        return RetVal.fail().message("获取抢购码失败，请登录");
    }

    //4.秒杀预下单  //api.gmall.com/seckill/prepareSeckill/null?seckillCode=null
    @PostMapping("prepareSeckill/{skuId}")
    public RetVal prepareSeckill(@PathVariable Long skuId, String seckillCode ,HttpServletRequest request){
        //1.判断抢购码是否正确
        String userId = AuthContextHolder.getUserId(request);
        if (!MD5.encrypt(userId).equals(seckillCode)){
            return RetVal.build(null, RetValCodeEnum.SECKILL_ILLEGAL);
        }
        //2.判断秒杀状态为1
        String seckillState = (String) redisTemplate.opsForValue().get(RedisConst.SECKILL_STATE_PREFIX + skuId);
        if (StringUtils.isEmpty(seckillState)){
            return RetVal.build(null, RetValCodeEnum.SECKILL_ILLEGAL);
        }
        //3.如果可以秒杀 发送消息到MQ起到削峰 生成一个秒杀预下单
        if (seckillState.equals(RedisConst.CAN_SECKILL)){
            UserSeckillSkuInfo userSeckillSkuInfo = new UserSeckillSkuInfo();
            userSeckillSkuInfo.setSkuId(skuId);
            userSeckillSkuInfo.setUserId(userId);
            rabbitTemplate.convertAndSend(MqConst.PREPARE_SECKILL_EXCHANGE,MqConst.PREPARE_SECKILL_ROUTE_KEY,userSeckillSkuInfo);
        }else {
            //秒杀售完
            return RetVal.build(null,RetValCodeEnum.SECKILL_FINISH);
        }
        return RetVal.ok();
    }

    //5.判断用户是否具备抢购资格
    @GetMapping("hasQualified/{skuId}")
    public RetVal hasQualified(@PathVariable Long skuId,HttpServletRequest request){
        String userId = AuthContextHolder.getUserId(request);
        return seckillProductService.hasQualified(skuId,userId);
    }

    //6.返回秒杀确认页面需要的数据信息
    @GetMapping("seckillConfirm")
    public RetVal seckillConfirm(HttpServletRequest request){
        String userId = AuthContextHolder.getUserId(request);

        return seckillProductService.seckillConfirm(userId);
    }

    //7.提交订单
    @PostMapping("submitSecKillOrder")
    public RetVal submitSecKillOrder(@RequestBody OrderInfo orderInfo,HttpServletRequest request){
        String userId = AuthContextHolder.getUserId(request);
        //获取用户的临时订单信息
        PrepareSeckillOrder prepareSeckillOrder= (PrepareSeckillOrder) redisTemplate.boundHashOps(RedisConst.PREPARE_SECKILL_USERID_ORDER).get(userId);
        if (prepareSeckillOrder == null) {
            return RetVal.fail().message("非法请求");
        }
        //远程调用order提交订单
        Long orderId = orderFeignClient.saveOrderAndDetail(orderInfo);
        if (orderId == null) {
            return RetVal.fail().message("下单失败，请重新下单");
        }
        //删除redis中临时订单数据
        redisTemplate.boundHashOps(RedisConst.PREPARE_SECKILL_USERID_ORDER).delete(userId);
        //把用户购买的商品信息存到redis
        redisTemplate.boundHashOps(RedisConst.BOUGHT_SECKILL_USER_ORDER).put(userId,orderId);

        return RetVal.ok();
    }
}

